From d7d77c20cfc3a0cbb385d10510941fd53a12de99 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 2 Sep 2005 17:55:24 +0000 Subject: [PATCH] Attached are the patches for new ioemu communication mechanism. The new mechanism provides richer I/O operation semantics, such as and,or,xor operation on MMIO space. This is necessary for operating systems such as Windows XP and Windows 2003. This is the first part of a two part patch. This patch applies to ioemu. Signed-Off-By: Leendert van Doorn --- tools/ioemu/exec.c | 7 +- tools/ioemu/target-i386-dm/helper2.c | 264 ++++++++++++++++++--------- tools/ioemu/vl.c | 5 + 3 files changed, 183 insertions(+), 93 deletions(-) diff --git a/tools/ioemu/exec.c b/tools/ioemu/exec.c index 286b3cd7f0..64cc7ef005 100644 --- a/tools/ioemu/exec.c +++ b/tools/ioemu/exec.c @@ -142,6 +142,10 @@ void cpu_set_log(int log_flags) #else setvbuf(logfile, NULL, _IOLBF, 0); #endif +/* + stdout = logfile; + stderr = logfile; +*/ } } @@ -386,9 +390,6 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val); l = 2; } else { - if (l!=1){ - fprintf(logfile, "ERROR 8 bit mmio\n"); - } /* 8 bit access */ val = ldub_raw(buf); io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val); diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index c3b740e3e5..4ee1410b20 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -169,133 +169,217 @@ ioreq_t* cpu_get_ioreq(void) unsigned long do_inp(CPUState *env, unsigned long addr, unsigned long size) { - switch(size) { - case 1: - return cpu_inb(env, addr); - case 2: - return cpu_inw(env, addr); - case 4: - return cpu_inl(env, addr); - default: - fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size); - exit(-1); - } + switch(size) { + case 1: + return cpu_inb(env, addr); + case 2: + return cpu_inw(env, addr); + case 4: + return cpu_inl(env, addr); + default: + fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size); + exit(-1); + } } void do_outp(CPUState *env, unsigned long addr, unsigned long size, unsigned long val) { - switch(size) { - case 1: - return cpu_outb(env, addr, val); - case 2: - return cpu_outw(env, addr, val); - case 4: - return cpu_outl(env, addr, val); - default: - fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size); - exit(-1); - } + switch(size) { + case 1: + return cpu_outb(env, addr, val); + case 2: + return cpu_outw(env, addr, val); + case 4: + return cpu_outl(env, addr, val); + default: + fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size); + exit(-1); + } } extern void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, int len, int is_write); static inline void -read_physical(target_phys_addr_t addr, unsigned long size, void *val) +read_physical(u64 addr, unsigned long size, void *val) { - return cpu_physical_memory_rw(addr, val, size, 0); + return cpu_physical_memory_rw((target_phys_addr_t)addr, val, size, 0); } static inline void -write_physical(target_phys_addr_t addr, unsigned long size, void *val) +write_physical(u64 addr, unsigned long size, void *val) { - return cpu_physical_memory_rw(addr, val, size, 1); + return cpu_physical_memory_rw((target_phys_addr_t)addr, val, size, 1); } -//send the ioreq to device model -void cpu_dispatch_ioreq(CPUState *env, ioreq_t *req) +void +cpu_ioreq_pio(CPUState *env, ioreq_t *req) { - int i; - int sign; + int i, sign; + + sign = req->df ? -1 : 1; + + if (req->dir == IOREQ_READ) { + if (!req->pdata_valid) { + req->u.data = do_inp(env, req->addr, req->size); + } else { + unsigned long tmp; - sign = (req->df) ? -1 : 1; + for (i = 0; i < req->count; i++) { + tmp = do_inp(env, req->addr, req->size); + write_physical((target_phys_addr_t) req->u.pdata + + (sign * i * req->size), + req->size, &tmp); + } + } + } else if (req->dir == IOREQ_WRITE) { + if (!req->pdata_valid) { + do_outp(env, req->addr, req->size, req->u.data); + } else { + for (i = 0; i < req->count; i++) { + unsigned long tmp; - if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) { - if (req->size != 4) { - // Bochs expects higher bits to be 0 - req->u.data &= (1UL << (8 * req->size))-1; + read_physical((target_phys_addr_t) req->u.pdata + + (sign * i * req->size), + req->size, &tmp); + do_outp(env, req->addr, req->size, tmp); + } } } +} + +void +cpu_ioreq_move(CPUState *env, ioreq_t *req) +{ + int i, sign; + + sign = req->df ? -1 : 1; - if (req->port_mm == 0){//port io - if(req->dir == IOREQ_READ){//read - if (!req->pdata_valid) { - req->u.data = do_inp(env, req->addr, req->size); - } else { - unsigned long tmp; - - for (i = 0; i < req->count; i++) { - tmp = do_inp(env, req->addr, req->size); - write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), - req->size, &tmp); - } + if (!req->pdata_valid) { + if (req->dir == IOREQ_READ) { + for (i = 0; i < req->count; i++) { + read_physical(req->addr + + (sign * i * req->size), + req->size, &req->u.data); } - } else if(req->dir == IOREQ_WRITE) { - if (!req->pdata_valid) { - do_outp(env, req->addr, req->size, req->u.data); - } else { - for (i = 0; i < req->count; i++) { - unsigned long tmp; - - read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, - &tmp); - do_outp(env, req->addr, req->size, tmp); - } + } else if (req->dir == IOREQ_WRITE) { + for (i = 0; i < req->count; i++) { + write_physical(req->addr + + (sign * i * req->size), + req->size, &req->u.data); } - } - } else if (req->port_mm == 1){//memory map io - if (!req->pdata_valid) { - //handle stos - if(req->dir == IOREQ_READ) { //read - for (i = 0; i < req->count; i++) { - read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &req->u.data); - } - } else if(req->dir == IOREQ_WRITE) { //write - for (i = 0; i < req->count; i++) { - write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &req->u.data); - } + } else { + unsigned long tmp; + + if (req->dir == IOREQ_READ) { + for (i = 0; i < req->count; i++) { + read_physical(req->addr + + (sign * i * req->size), + req->size, &tmp); + write_physical((target_phys_addr_t )req->u.pdata + + (sign * i * req->size), + req->size, &tmp); } - } else { - //handle movs - unsigned long tmp; - if (req->dir == IOREQ_READ) { - for (i = 0; i < req->count; i++) { - read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &tmp); - write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp); - } - } else if (req->dir == IOREQ_WRITE) { - for (i = 0; i < req->count; i++) { - read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp); - write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &tmp); - } + } else if (req->dir == IOREQ_WRITE) { + for (i = 0; i < req->count; i++) { + read_physical((target_phys_addr_t) req->u.pdata + + (sign * i * req->size), + req->size, &tmp); + write_physical(req->addr + + (sign * i * req->size), + req->size, &tmp); } } } - /* No state change if state = STATE_IORESP_HOOK */ - if (req->state == STATE_IOREQ_INPROCESS) - req->state = STATE_IORESP_READY; - env->send_event = 1; +} + +void +cpu_ioreq_and(CPUState *env, ioreq_t *req) +{ + unsigned long tmp1, tmp2; + + if (req->pdata_valid != 0) + hw_error("expected scalar value"); + + read_physical(req->addr, req->size, &tmp1); + if (req->dir == IOREQ_WRITE) { + tmp2 = tmp1 & (unsigned long) req->u.data; + write_physical(req->addr, req->size, &tmp2); + } + req->u.data = tmp1; +} + +void +cpu_ioreq_or(CPUState *env, ioreq_t *req) +{ + unsigned long tmp1, tmp2; + + if (req->pdata_valid != 0) + hw_error("expected scalar value"); + + read_physical(req->addr, req->size, &tmp1); + if (req->dir == IOREQ_WRITE) { + tmp2 = tmp1 | (unsigned long) req->u.data; + write_physical(req->addr, req->size, &tmp2); + } + req->u.data = tmp1; +} + +void +cpu_ioreq_xor(CPUState *env, ioreq_t *req) +{ + unsigned long tmp1, tmp2; + + if (req->pdata_valid != 0) + hw_error("expected scalar value"); + + read_physical(req->addr, req->size, &tmp1); + if (req->dir == IOREQ_WRITE) { + tmp2 = tmp1 ^ (unsigned long) req->u.data; + write_physical(req->addr, req->size, &tmp2); + } + req->u.data = tmp1; } void cpu_handle_ioreq(CPUState *env) { ioreq_t *req = cpu_get_ioreq(); - if (req) - cpu_dispatch_ioreq(env, req); + + if (req) { + if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) { + if (req->size != 4) + req->u.data &= (1UL << (8 * req->size))-1; + } + + switch (req->type) { + case IOREQ_TYPE_PIO: + cpu_ioreq_pio(env, req); + break; + case IOREQ_TYPE_COPY: + cpu_ioreq_move(env, req); + break; + case IOREQ_TYPE_AND: + cpu_ioreq_and(env, req); + break; + case IOREQ_TYPE_OR: + cpu_ioreq_or(env, req); + break; + case IOREQ_TYPE_XOR: + cpu_ioreq_xor(env, req); + break; + default: + hw_error("Invalid ioreq type 0x%x", req->type); + } + + /* No state change if state = STATE_IORESP_HOOK */ + if (req->state == STATE_IOREQ_INPROCESS) + req->state = STATE_IORESP_READY; + env->send_event = 1; + } } void @@ -321,7 +405,7 @@ do_interrupt(CPUState *env, int vector) // Send a message on the event channel. Add the vector to the shared mem // page. - intr = &(shared_page->sp_global.pic_intr[0]); + intr = (unsigned long *) &(shared_page->sp_global.pic_intr[0]); atomic_set_bit(vector, intr); if (loglevel & CPU_LOG_INT) fprintf(logfile, "injecting vector: %x\n", vector); diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index c274f42e2e..d5d00d22d8 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -413,6 +413,11 @@ void hw_error(const char *fmt, ...) fprintf(stderr, "qemu: hardware error: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); + if (logfile) { + fprintf(logfile, "qemu: hardware error: "); + vfprintf(logfile, fmt, ap); + fprintf(logfile, "\n"); + } va_end(ap); abort(); } -- 2.30.2